function getPaperCraneModel() {
	var testModel = createEmptyPaper(1000, 1000, 0.1);
	foldSinglePlane(testModel, testModel.planes[0],{start:{x:0,y:1000,z:0},end:{x:1000,y:0,z:0}}, -180, true);
	foldInsidePlane(testModel, testModel.planes[0],{start:{x:500,y:500,z:0},end:{x:1000,y:500,z:0}}, true);
	foldInsidePlane(testModel, testModel.planes[0],{start:{x:499.9,y:500,z:0},end:{x:500,y:1000,z:0}}, true);
	
	foldInsidePlane(testModel, testModel.planes[4],{start:{x:1000,y:1000,z:0},end:{x:792.8932188,y:500,z:0}}, true);
	foldInsidePlane(testModel, testModel.planes[1],{start:{x:1000,y:1000,z:0},end:{x:500,y:792.8932188,z:0}}, true);
	
	foldInsidePlane(testModel, testModel.planes[6],{start:{x:1000,y:1000,z:0},end:{x:792.8932188,y:500,z:0}}, true);
	foldInsidePlane(testModel, testModel.planes[2],{start:{x:1000,y:1000,z:0},end:{x:500,y:792.8932188,z:0}}, true);
	
	foldSuperPlane(testModel, [2,6,5], {start:{x:500,y:792.8932188,z:0},end:{x:792.8932188,y:500,z:0}}, -180, false);
	foldSuperPlane(testModel, [9,12,13], {start:{x:500,y:792.8932188,z:0},end:{x:792.8932188,y:500,z:0}}, 180, false);
	
	foldSuperPlane(testModel, [10,11,13,16,17], {start:{x:1000,y:1000,z:0},end:{x:500,y:665.9106810,z:0}}, 180, false);
	foldSuperPlane(testModel, [3,4,6,14,15], {start:{x:1000,y:1000,z:0},end:{x:500,y:665.9106810,z:0}}, -180, false);
	foldSuperPlane(testModel, [7,8,9,13,17], {start:{x:1000,y:1000,z:0},end:{x:665.9106810,y:500,z:0}}, 180, true);
	foldSuperPlane(testModel, [0,1,2,6,14] , {start:{x:1000,y:1000,z:0},end:{x:665.9106810,y:500,z:0}}, -180, true);
	
	foldSuperPlane(testModel, [3,4,23,24], {start:{x:646.4466094,y:646.4466094,z:0},end:{x:625,y:700,z:0}}, 180, false);
	foldSuperPlane(testModel, [10,11,18,19], {start:{x:646.4466094,y:646.4466094,z:0},end:{x:625,y:700,z:0}}, -180, false);
	foldSuperPlane(testModel, [0,1,33,34], {start:{x:646.4466094,y:646.4466094,z:0},end:{x:700,y:625,z:0}}, 180, false);
	foldSuperPlane(testModel, [7,8,28,29], {start:{x:646.4466094,y:646.4466094,z:0},end:{x:700,y:625,z:0}}, -180, false);
	
	foldSuperPlane(testModel, [9,16,17,21,22,30,32], {start:{x:665.910681,y:500,z:0},end:{x:500,y:665.910681,z:0}}, 90, true);
	foldSuperPlane(testModel, [2,14,15,26,27,35,37], {start:{x:665.910681,y:500,z:0},end:{x:500,y:665.910681,z:0}}, -90, true);
	
	foldSuperPlane(testModel, [38,39,40,41], {start:{x:440,y:500,z:0},end:{x:0,y:940,z:0}}, 180, true);
	foldSuperPlane(testModel, [42,43,44,45], {start:{x:440,y:500,z:0},end:{x:0,y:940,z:0}}, -180, true);

	return testModel;
}

function getPaperPlaneModel() {
	var testModel = createEmptyPaper(1000, 1414, 0.1);
	foldSinglePlane(testModel, testModel.planes[0],{start:{x:500,y:0,z:0},end:{x:1000,y:500,z:0}}, -180,true);
	foldSinglePlane(testModel, testModel.planes[0],{start:{x:500,y:0,z:0},end:{x:0,y:500,z:0}}, 180,true);
	foldSinglePlane(testModel, testModel.planes[0],{start:{x:500,y:0,z:0},end:{x:1000,y:1207.1067812,z:0}}, -180,true);
	foldSinglePlane(testModel, testModel.planes[0],{start:{x:500,y:0,z:0},end:{x:0,y:1207.1067812,z:0}}, 180,true);

	foldSinglePlane(testModel, testModel.planes[0],{start:{x:500,y:0,z:0},end:{x:500,y:1000,z:0}}, 180,true);
	foldSinglePlane(testModel, testModel.planes[2],{start:{x:500,y:0,z:0},end:{x:1000,y:2513.6697461,z:0}}, 90,true);
	foldSinglePlane(testModel, testModel.planes[4],{start:{x:500,y:0,z:0},end:{x:1000,y:2513.6697461,z:0}}, -90,true);

	return testModel;
}

function foldPaperCrane(){
	var f = createEmptyPaper(1000, 1000, 0.1);
	var retList = [];
	retList.push(cloneModel(f));
	
	foldSinglePlaneEX(retList, f, 0, {x:0,y:1000,z:0}, {x:1000,y:0,z:0}, 0, -180, true);
	foldInsidePlaneEX(retList, f, 0, {x:1000,y:0,z:0}, {x:500,y:500,z:0}, {x:1000,y:0,z:0}, {x:1000,y:500,z:0}, true);
	foldInsidePlaneEX(retList, f, 0, {x:0,y:1000,z:0}, {x:499.9,y:500,z:0}, {x:0,y:1000,z:0}, {x:500,y:1000,z:0}, true);
	
	foldInsidePlaneEX(retList, f, 4, {x:1000,y:500,z:0}, {x:1000,y:1000,z:0}, {x:1000,y:500,z:0},{x:792.8932188,y:500,z:0}, true);
	foldInsidePlaneEX(retList, f, 1, {x:500,y:1000,z:0}, {x:1000,y:1000,z:0}, {x:500,y:1000,z:0},{x:500,y:792.8932188,z:0}, false);
	
	foldInsidePlaneEX(retList, f, 6, {x:1000,y:500,z:0}, {x:1000,y:1000,z:0}, {x:1000,y:500,z:0},{x:792.8932188,y:500,z:0}, true);
	foldInsidePlaneEX(retList, f, 2, {x:500,y:1000,z:0}, {x:1000,y:1000,z:0}, {x:500,y:1000,z:0},{x:500,y:792.8932188,z:0}, false);
	
	foldSuperPlaneEX(retList, f, [2,6,5], {start:{x:500,y:792.8932188,z:0},end:{x:792.8932188,y:500,z:0}}, 0, -180, false);
	foldSuperPlaneEX(retList, f, [9,12,13], {start:{x:500,y:792.8932188,z:0},end:{x:792.8932188,y:500,z:0}}, 0, 180, false);
	
	foldSuperPlaneEX(retList, f, [10,11,13,16,17], {start:{x:1000,y:1000,z:0},end:{x:500,y:665.9106810,z:0}}, 0, 180, false);
	foldSuperPlaneEX(retList, f, [3,4,6,14,15], {start:{x:1000,y:1000,z:0},end:{x:500,y:665.9106810,z:0}}, 0, -180, false);
	foldSuperPlaneEX(retList, f, [7,8,9,13,17], {start:{x:1000,y:1000,z:0},end:{x:665.9106810,y:500,z:0}}, 0, 180, true);
	foldSuperPlaneEX(retList, f, [0,1,2,6,14], {start:{x:1000,y:1000,z:0},end:{x:665.9106810,y:500,z:0}}, 0, -180, true);
		
	foldSuperPlaneEXDouble(retList, f,  [3,4,23,24], [10,11,18,19], {x:1000,y:1000,z:0}, {x:646.4466094,y:646.4466094,z:0}, {x:1000,y:1000,z:0}, {x:625,y:700,z:0}, 180, -180, false);
	foldSuperPlaneEXDouble(retList, f,  [0,1,33,34], [7,8,28,29], {x:1000,y:1000,z:0}, {x:646.4466094,y:646.4466094,z:0}, {x:1000,y:1000,z:0}, {x:700,y:625,z:0}, 180, -180, false);
	
	foldSuperPlaneEX(retList, f, [9,16,17,21,22,30,32], {start:{x:665.910681,y:500,z:0},end:{x:500,y:665.910681,z:0}}, 0, 90, true);
	foldSuperPlaneEX(retList, f, [2,14,15,26,27,35,37], {start:{x:665.910681,y:500,z:0},end:{x:500,y:665.910681,z:0}}, 0, -90, true);
	
	
	foldSuperPlaneEXDouble(retList, f,  [38,39,40,41],[42,43,44,45], {x:330,y:500,z:0},{x:440,y:500,z:0}, {x:0,y:830,z:0}, {x:0,y:940,z:0}, 180, -180, true);
	
	return retList;
}

function foldPaperPlane(){
	var f = createEmptyPaper(1000, 1414, 0.1);
	var retList = [];
	retList.push(cloneModel(f));
	
	foldSinglePlaneEX(retList, f, 0, {x:500,y:0,z:0}, {x:1000,y:500,z:0}, 0, -180, true);
	foldSinglePlaneEX(retList, f, 0, {x:500,y:0,z:0}, {x:0,y:500,z:0}, 0, 180, true);
	foldSinglePlaneEX(retList, f, 0, {x:500,y:0,z:0}, {x:1000,y:1207.1067812,z:0}, 0, -180, true);
	foldSinglePlaneEX(retList, f, 0, {x:500,y:0,z:0}, {x:0,y:1207.1067812,z:0}, 0, 180, true);
	
	foldSinglePlaneEX(retList, f, 0, {x:500,y:0,z:0}, {x:500,y:1000,z:0}, 0, 180, true);
	foldSinglePlaneEX(retList, f, 2, {x:500,y:0,z:0}, {x:1000,y:2513.6697461,z:0}, 0, 90, true);
	foldSinglePlaneEX(retList, f, 4, {x:500,y:0,z:0}, {x:1000,y:2513.6697461,z:0}, 0, -90, true);
	
	return retList;
}

function foldSinglePlaneEX(list, f, index, s, end, as, ae, check){
	var t;
	for(var i = 1; i < 23; i++){
		t = cloneModel(f);
		foldSinglePlane(t, t.planes[index],{start:s,end:end}, as+(ae-as)/24*i, check);
		list.push(t);
	}
	foldSinglePlane(f, f.planes[index],{start:s,end:end}, ae, true);
	list.push(cloneModel(f));
}

function foldInsidePlaneEX(list, f, index, ss, se, es, ee, check){
	function makeStep(s, e, step){
		return {x:s.x+(e.x-s.x)/24*step,y:s.y+(e.y-s.y)/24*step,z:s.z+(e.z-s.z)/24*step}
	}
	var t;
	for(var i = 1; i < 23; i++){
		t = cloneModel(f);
		foldInsidePlane(t, t.planes[index],{start:makeStep(ss,se,i),end:makeStep(es,ee,i)}, check);
		list.push(t);
	}
	foldInsidePlane(f, f.planes[index],{start:se,end:ee}, check);
	list.push(cloneModel(f));	
}

function foldSuperPlaneEX(list, f, patches, edge, as, ae, check){
	var t;
	for(var i = 1; i < 23; i++){
		t = cloneModel(f);
		foldSuperPlane(t, patches, edge, as+(ae - as)/24*i,check);
		list.push(t);
	}
	foldSuperPlane(f, patches, edge, ae, check);
	list.push(cloneModel(f));
}

function foldSuperPlaneEXDouble(list, f, p1, p2, ss, se, es, ee, a1, a2, check){
	function makeStep(s, e, step){
		return {x:s.x+(e.x-s.x)/24*step,y:s.y+(e.y-s.y)/24*step,z:s.z+(e.z-s.z)/24*step}
	}
	for(var i = 1; i < 23; i++){
		t = cloneModel(f);
		foldSuperPlane(t, p1, {start:makeStep(ss,se,i),end:makeStep(es,ee,i)},a1,check);
		foldSuperPlane(t, p2, {start:makeStep(ss,se,i),end:makeStep(es,ee,i)},a2,check);
		list.push(t);
	}
	foldSuperPlane(f, p1, {start:se, end:ee}, a1, check);
	foldSuperPlane(f, p2, {start:se, end:ee}, a2, check);
	list.push(cloneModel(f));
}

var modelCanvas = null;
var paperCanvas = null;
var modelView = null;
var paperView = null;

function createViewers(model) {
	modelCanvas = document.getElementById("model-3d-canvas");
	modelCanvas.width = window.innerWidth;
    modelCanvas.height = window.innerHeight;
	paperCanvas = document.getElementById("crease-pattern-canvas");
	modelView = new Model3DViewer(modelCanvas, model);
	paperView = new CreasePatternViewer(paperCanvas, model);
	paperView.pointTouched(function(point, patch) {
		point = changeCoordinatePoint3(point, patch.coordinate, normalCoordinate);
		modelView.removeAllSelectedPoints();
		modelView.addSelectedPoint(point);
	});
	paperView.setSize(window.innerWidth * 0.5, window.innerHeight * 0.618);
}

var currentAnimation = null;

function showModel(model) {
	if (currentAnimation) {
		currentAnimation.enabled = false;
		currentAnimation = null;
	}
	createViewers(model);
	modelView.start();
	paperView.draw();
}

function showAnimatedModel(modelList, interval) {
	if (!modelList || modelList.length == 0) {
		return;
	}
	var model = createEmptyPaper(modelList[0].width, modelList[0].height, 0.1);
	createViewers(model);
	modelView.start();
	var step = 0;
	var animation = { enabled: true }; // create new controller object
	function showSteps() {
		if (!animation.enabled) {
			return;
		}
		model.bak = modelList[step];
		changeModeltoBak(model);
		modelView.refreshModel();
		paperView.draw();
		setTimeout(showSteps, interval);
		step = (step + 1) % modelList.length;
	}
	if (currentAnimation) {
		currentAnimation.enabled = false;
	}
	currentAnimation = animation; 
	showSteps();
}

window.addEventListener("load", function() {
	var models = {};
	document.getElementById("plane-button").addEventListener("click", function() {
		if (!models.plane) {
			models.plane = getPaperPlaneModel();
		}
		showModel(models.plane);
	});
	document.getElementById("crane-button").addEventListener("click", function() {
		if (!models.crane) {
			models.crane = getPaperCraneModel();
		}
		showModel(models.crane);
	});
	document.getElementById("plane-animated-button").addEventListener("click", function() {
		if (!models.animatedPlane) {
			models.animatedPlane = foldPaperPlane();
		}
		showAnimatedModel(models.animatedPlane, 100);
	});
	document.getElementById("crane-animated-button").addEventListener("click", function() {
		if (!models.animatedCrane) {
			models.animatedCrane = foldPaperCrane();
		}
		showAnimatedModel(models.animatedCrane, 40);
	});
});

window.addEventListener("resize", function() {
	if (modelCanvas && modelView) {
		modelView.resetViewport(window.innerWidth, window.innerHeight);
	} 
	if (paperCanvas && paperView) {
		paperView.setSize(window.innerWidth * 0.5, window.innerHeight * 0.618);
		paperView.draw();
	}
});